In [271]:
import pandas as pd
import numpy as np
import plotly.express as px
import matplotlib.pyplot as plt
import seaborn as sns
In [272]:
import warnings
warnings.filterwarnings('ignore')
In [279]:
import plotly

plotly.offline.init_notebook_mode()
In [280]:
df = pd.read_csv(
    'MICRODADOS_ENEM_2019.csv',
    header=0,
    encoding = "ISO-8859-1",
    sep=';',
    skiprows=lambda i: i>0 and np.random.rand() > 0.005,
)

df.head()
Out[280]:
NU_INSCRICAO NU_ANO TP_FAIXA_ETARIA TP_SEXO TP_ESTADO_CIVIL TP_COR_RACA TP_NACIONALIDADE TP_ST_CONCLUSAO TP_ANO_CONCLUIU TP_ESCOLA ... Q016 Q017 Q018 Q019 Q020 Q021 Q022 Q023 Q024 Q025
0 190001121526 2019 9 M 1 3 1 1 6 1 ... A A A C B A B A A B
1 190001339057 2019 2 M 1 3 1 3 0 1 ... A A A B A A B A A A
2 190001599158 2019 11 F 1 3 1 1 9 1 ... A A A B A A C B B B
3 190001241370 2019 5 F 1 1 1 1 2 1 ... A A A A A A B A A B
4 190001500503 2019 10 F 1 3 1 2 0 2 ... A A A B A A B A A B

5 rows × 76 columns

In [281]:
answers = ['TX_RESPOSTAS_CN', 'TX_RESPOSTAS_CH', 'TX_RESPOSTAS_LC', 'TX_RESPOSTAS_MT']
correct_answers = ['TX_GABARITO_CN', 'TX_GABARITO_CH', 'TX_GABARITO_LC', 'TX_GABARITO_MT']
scores = ['NU_NOTA_CN', 'NU_NOTA_CH', 'NU_NOTA_LC', 'NU_NOTA_MT','NU_NOTA_REDACAO']
foreign_language = ['TP_LINGUA']
questions = ['TP_SEXO', 'TP_COR_RACA', 'Q001', 'Q002', 'TP_DEPENDENCIA_ADM_ESC']

df = df[['NU_INSCRICAO']+foreign_language+answers+correct_answers+scores+questions]
In [282]:
df.shape
Out[282]:
(25272, 20)
In [283]:
df['TP_SEXO'].replace({'M': 'Masculino',
                               'F': 'Feminino'}, inplace=True)
df['TP_COR_RACA'].replace({0:'Não declarada',
                                   1:'Branca',
                                   2:'Preta',
                                   3:'Parda',
                                   4:'Amarela',
                                   5:'Indígena'}, inplace=True)
df['Q001'].replace({'A': 'Nunca estudou',
                            'B': 'Fund. incompleto',
                            'C': 'Fund. incompleto', 
                            'D': 'Medio incompleto',
                            'E': 'Medio completo',
                            'F': 'Superior completo',
                            'G': 'Pós graduação',
                            'H': 'Não sabe'}, inplace=True)
df['Q002'].replace({'A': 'Nunca estudou',
                            'B': 'Fund. incompleto',
                            'C': 'Fund. incompleto', 
                            'D': 'Medio incompleto',
                            'E': 'Medio completo',
                            'F': 'Superior completo',
                            'G': 'Pós graduação',
                            'H': 'Não sabe'}, inplace=True)
df['TP_DEPENDENCIA_ADM_ESC'].replace({1: 'Federal',
                         2: 'Estadual',
                         3: 'Municipal',
                         4: 'Privada'}, inplace=True)
In [284]:
df['NU_MEDIA_NOTA'] = df[['NU_NOTA_CN', 'NU_NOTA_CH', 'NU_NOTA_LC', 'NU_NOTA_MT', 'NU_NOTA_REDACAO']].sum(axis=1)/5
In [285]:
df = df[(df['NU_NOTA_LC'] != 0) &
        (df['NU_NOTA_CH'] != 0) & 
        (df['NU_NOTA_CN'] != 0) &
        (df['NU_NOTA_MT'] != 0)]
In [286]:
df['TX_RESPOSTAS_LC'] = df['TX_RESPOSTAS_LC'].str.replace('9', '')
In [287]:
df.loc[df.TP_LINGUA == 0, 'TX_GABARITO_LC'] = df.query('TP_LINGUA ==0')['TX_GABARITO_LC'].str.slice(stop=5)+df['TX_GABARITO_LC'].str.slice(start=10)
df.loc[df.TP_LINGUA == 1, 'TX_GABARITO_LC'] = df['TX_GABARITO_LC'].str.slice(start=5)
In [288]:
df = df.dropna(subset=['TX_RESPOSTAS_CN', 'TX_RESPOSTAS_CH', 'TX_RESPOSTAS_LC', 'TX_RESPOSTAS_MT'])
In [289]:
df['ACERTOS_CN'] = df.apply(lambda x: np.sum(np.array(list(x['TX_RESPOSTAS_CN'])) == np.array(list(x['TX_GABARITO_CN']))), axis=1)
df['ACERTOS_CH'] = df.apply(lambda x: np.sum(np.array(list(x['TX_RESPOSTAS_CH'])) == np.array(list(x['TX_GABARITO_CH']))), axis=1)
df['ACERTOS_LC'] = df.apply(lambda x: np.sum(np.array(list(x['TX_RESPOSTAS_LC'])) == np.array(list(x['TX_GABARITO_LC']))), axis=1)
df['ACERTOS_MT'] = df.apply(lambda x: np.sum(np.array(list(x['TX_RESPOSTAS_MT'])) == np.array(list(x['TX_GABARITO_MT']))), axis=1)
In [290]:
df.dtypes
Out[290]:
NU_INSCRICAO                int64
TP_LINGUA                   int64
TX_RESPOSTAS_CN            object
TX_RESPOSTAS_CH            object
TX_RESPOSTAS_LC            object
TX_RESPOSTAS_MT            object
TX_GABARITO_CN             object
TX_GABARITO_CH             object
TX_GABARITO_LC             object
TX_GABARITO_MT             object
NU_NOTA_CN                float64
NU_NOTA_CH                float64
NU_NOTA_LC                float64
NU_NOTA_MT                float64
NU_NOTA_REDACAO           float64
TP_SEXO                    object
TP_COR_RACA                object
Q001                       object
Q002                       object
TP_DEPENDENCIA_ADM_ESC     object
NU_MEDIA_NOTA             float64
ACERTOS_CN                  int32
ACERTOS_CH                  int32
ACERTOS_LC                  int32
ACERTOS_MT                  int32
dtype: object
In [291]:
df.drop(columns=['TP_LINGUA']).describe()
Out[291]:
NU_INSCRICAO NU_NOTA_CN NU_NOTA_CH NU_NOTA_LC NU_NOTA_MT NU_NOTA_REDACAO NU_MEDIA_NOTA ACERTOS_CN ACERTOS_CH ACERTOS_LC ACERTOS_MT
count 1.832500e+04 18325.000000 18325.000000 18325.000000 18325.000000 18325.000000 18325.000000 18325.000000 18325.000000 18325.000000 18325.000000
mean 1.900035e+11 477.413670 509.162172 522.009332 523.314106 579.257844 522.231425 13.103029 16.753888 18.697954 11.615225
std 1.449676e+06 75.364576 79.910306 62.106127 108.467878 182.793858 83.257499 4.872235 6.922033 7.117213 5.431511
min 1.900010e+11 327.900000 315.900000 322.000000 359.000000 0.000000 292.320000 0.000000 0.000000 0.000000 0.000000
25% 1.900022e+11 418.300000 449.800000 485.200000 435.800000 500.000000 464.520000 10.000000 11.000000 13.000000 8.000000
50% 1.900034e+11 469.900000 512.700000 527.400000 502.000000 580.000000 514.380000 12.000000 16.000000 18.000000 10.000000
75% 1.900047e+11 530.800000 567.200000 565.500000 597.500000 680.000000 576.020000 16.000000 21.000000 24.000000 14.000000
max 1.900061e+11 795.000000 769.100000 739.900000 984.200000 1000.000000 807.140000 40.000000 42.000000 42.000000 43.000000
In [292]:
fig = px.histogram(df['NU_NOTA_LC'], color_discrete_sequence=['#f5d86e'])
fig.update_layout(title='Distribuição das notas de Linguagens e Códigos')
In [293]:
fig = px.histogram(df['NU_NOTA_CH'],color_discrete_sequence=['#b46ef5'])
fig.update_layout(title='Distribuição das notas de Ciencias Humanas')
In [294]:
fig = px.histogram(df['NU_NOTA_MT'], color_discrete_sequence=['#6e92f5'])
fig.update_layout(title='Distribuição das notas de Matemática')
In [295]:
fig = px.histogram(df['NU_NOTA_CN'], color_discrete_sequence=['#6ef587'])
fig.update_layout(title='Distribuição das notas de Ciencias da Natureza')
In [296]:
fig = px.histogram(df['NU_NOTA_REDACAO'], color_discrete_sequence=['#f56e6e'])
fig.update_layout(title='Distribuição das notas de Redação')
In [297]:
import statsmodels.api as sm

fig, axes = plt.subplots(3, 2, figsize=(20, 15))

fig = sm.qqplot(df['NU_NOTA_LC'], ax=axes[0,0])
fig = sm.qqplot(df['NU_NOTA_CH'], ax=axes[0,1])
fig = sm.qqplot(df['NU_NOTA_CN'], ax=axes[1,0])
fig = sm.qqplot(df['NU_NOTA_MT'], ax=axes[1,1])
fig = sm.qqplot(df['NU_NOTA_REDACAO'], ax=axes[2,0])


fig.suptitle('Graficos Q-Q para distribuição de notas em cada área de conhecimento', fontsize=16, y = 0.94)
axes[0, 0].set_title('Linguagens')
axes[0, 1].set_title('Ciências Humanas')
axes[0, 1].set_title('Ciências da Natureza')
axes[1, 1].set_title('Matemática')
axes[2, 0].set_title('Redação')

plt.show()
In [298]:
fig, axes = plt.subplots(2, 2, figsize=(20, 15))

sns.scatterplot(x=df['ACERTOS_LC'], y=df['NU_NOTA_LC'], ax=axes[0,0], color='r')
sns.scatterplot(x=df['ACERTOS_CH'], y=df['NU_NOTA_CH'], ax=axes[0,1], color='rebeccapurple')
sns.scatterplot(x=df['ACERTOS_CN'], y=df['NU_NOTA_CN'], ax=axes[1,0], color='g')
sns.scatterplot(x=df['ACERTOS_MT'], y=df['NU_NOTA_MT'], ax=axes[1,1])

fig.suptitle('Intervalo de pontuação de acordo com a quantidade de acertos', fontsize=16, y = 0.94)
axes[0, 0].set_title('Linguagens')
axes[0, 1].set_title('Ciências Humanas')
axes[0, 1].set_title('Ciências da Natureza')
axes[1, 1].set_title('Matemática')

plt.show()
In [299]:
px.histogram(df, x="TP_DEPENDENCIA_ADM_ESC", title='Quantidade de escolas por tipo de administração') 
In [300]:
px.pie(df,"TP_COR_RACA", title='Quantidade de inscritos por raça', hole = 0.7) 
In [301]:
px.box(
df.loc[(~df.TP_DEPENDENCIA_ADM_ESC.isna())], 
x= 'NU_MEDIA_NOTA', color='TP_DEPENDENCIA_ADM_ESC', title='Box plot das notas médias por escola',
category_orders={'TP_DEPENDENCIA_ADM_ESC': ['Estadual', 'Municipal', 'Federal', 'Privada']})
In [302]:
px.box(
df.loc[(~df.Q001.isna())], 
x= 'NU_MEDIA_NOTA', color='Q001', title='Box plot das notas médias por nivel de escolaridade do pai',
category_orders={'Q001': df.loc[(~df.Q001.isna())].groupby("Q001")['NU_MEDIA_NOTA'].mean().sort_values().keys()}
)
In [303]:
px.box(
df.loc[(~df.Q002.isna())], 
x= 'NU_MEDIA_NOTA', color='Q001', title='Box plot das notas médias por nivel de escolaridade da mãe',
category_orders={'Q001': df.loc[(~df.Q002.isna())].groupby("Q002")['NU_MEDIA_NOTA'].mean().sort_values().keys()}
)
In [304]:
fig = px.scatter_matrix(df[scores])
fig.update_layout(height=800, width=1000)
In [305]:
fig = px.scatter(df.loc[df.TP_DEPENDENCIA_ADM_ESC.isin(["Estadual", "Privada"])], x="ACERTOS_MT", y="NU_NOTA_MT", color="TP_DEPENDENCIA_ADM_ESC", trendline="ols")
fig.update_layout(title="Reta de regressão ACERTOS_MT ~ NU_NOTA_MT por tipo de admnistração escolar")
In [306]:
results = px.get_trendline_results(fig)

results.query("TP_DEPENDENCIA_ADM_ESC == 'Estadual'").px_fit_results.iloc[0].summary()
Out[306]:
OLS Regression Results
Dep. Variable: y R-squared: 0.706
Model: OLS Adj. R-squared: 0.705
Method: Least Squares F-statistic: 8769.
Date: Mon, 17 Apr 2023 Prob (F-statistic): 0.00
Time: 23:09:28 Log-Likelihood: -19417.
No. Observations: 3662 AIC: 3.884e+04
Df Residuals: 3660 BIC: 3.885e+04
Df Model: 1
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
const 304.9757 2.216 137.639 0.000 300.631 309.320
x1 18.7940 0.201 93.643 0.000 18.401 19.187
Omnibus: 32.796 Durbin-Watson: 1.955
Prob(Omnibus): 0.000 Jarque-Bera (JB): 30.287
Skew: -0.183 Prob(JB): 2.65e-07
Kurtosis: 2.746 Cond. No. 30.7


Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
In [307]:
results = px.get_trendline_results(fig)

results.query("TP_DEPENDENCIA_ADM_ESC == 'Privada'").px_fit_results.iloc[0].summary()
Out[307]:
OLS Regression Results
Dep. Variable: y R-squared: 0.865
Model: OLS Adj. R-squared: 0.865
Method: Least Squares F-statistic: 5092.
Date: Mon, 17 Apr 2023 Prob (F-statistic): 0.00
Time: 23:09:28 Log-Likelihood: -4108.1
No. Observations: 797 AIC: 8220.
Df Residuals: 795 BIC: 8230.
Df Model: 1
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
const 385.9415 3.796 101.661 0.000 378.489 393.394
x1 14.5626 0.204 71.356 0.000 14.162 14.963
Omnibus: 68.014 Durbin-Watson: 1.623
Prob(Omnibus): 0.000 Jarque-Bera (JB): 84.682
Skew: -0.735 Prob(JB): 4.09e-19
Kurtosis: 3.623 Cond. No. 47.6


Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
In [308]:
df_corr = df[scores].corr(
    method = 'pearson'
)

sns.heatmap(df_corr, annot=True)
plt.title("Matriz de correlação entre as notas das áreas de conhecimento")
plt.show()
In [309]:
crosstab=pd.crosstab(index=df['Q001'],columns=df['Q002'], normalize='columns', margins=True)
In [310]:
crosstab
Out[310]:
Q002 Fund. incompleto Medio completo Medio incompleto Nunca estudou Não sabe Pós graduação Superior completo All
Q001
Fund. incompleto 0.624875 0.238912 0.371596 0.347826 0.090551 0.113841 0.129583 0.337899
Medio completo 0.107833 0.438491 0.220360 0.041739 0.090551 0.279808 0.344550 0.272797
Medio incompleto 0.093482 0.123017 0.255970 0.031304 0.027559 0.075494 0.093420 0.119181
Nunca estudou 0.085509 0.014244 0.024298 0.530435 0.031496 0.005992 0.006529 0.050150
Não sabe 0.070361 0.077048 0.083368 0.043478 0.722441 0.040743 0.051231 0.086767
Pós graduação 0.005382 0.030107 0.012568 0.000000 0.013780 0.301977 0.113009 0.053424
Superior completo 0.012557 0.078181 0.031839 0.005217 0.023622 0.182145 0.261678 0.079782
In [ ]:
 
In [ ]:
 
In [ ]: